import BaseLayer from "ol/layer/Base";
import Collection from "ol/Collection";
import { Group as LayerGroup } from "ol/layer";

// t- 获取图层

/**
 * @description 获取地图中的所有图层(包括图层组中的图层)
 * @param {Map} map 地图对象
 * @returns {Array} 图层数组
 */
export function getLayers(map) {
  return [...map.getLayers().getArray(), ...map.getAllLayers()];
}

/**
 * @description 根据图层id获取图层
 * @param {Map} map 地图对象
 * @param {String} targetId 图层id
 * @returns {BaseLayer} 图层对象
 */
export function getLayerById(map, targetId) {
  const layers = getLayers(map);
  let targetLayer;
  for (let i = 0; i < layers.length; i++) {
    const layer = layers[i];
    if (!layer || !(layer instanceof BaseLayer)) continue;
    const id = layer.get("id") || layer.id;
    if (id === targetId) {
      targetLayer = layer;
      break;
    }
  }
  return targetLayer;
}

/**
 * @description 根据条件获取图层
 * @param {Map} map 地图对象
 * @param {Function} condition 条件函数,接收图层对象、图层id和图层数组作为参数，返回布尔值
 * @param {BaseLayer} condition.layer 图层对象
 * @param {String} condition.id 图层id
 * @param {Array} condition.layers 图层数组
 * @returns {BaseLayer[]} 所有满足条件的图层
 */
export function getLayerByCondition(map, condition) {
  const layers = getLayers(map);
  let targetLayers = [];
  for (let i = 0; i < layers.length; i++) {
    const layer = layers[i];
    if (!layer || !(layer instanceof BaseLayer)) continue;
    // 判断图层是否满足条件
    const id = layer.get("id") || layer.id;
    if (condition(layer, id, layers)) {
      targetLayers.push(layer);
    }
  }
  return targetLayers;
}

/**
 * @description 根据图层id获取它所在的图层组
 * @param {Map} map 地图对象
 * @param {String} targetId 图层id
 * @returns {LayerGroup | null} 图层组对象 , 如果图层不在图层组中,则返回null
 */
export function getGroupById(map, targetId) {
  let targetGroup = null;

  const layers = map.getLayerGroup();

  const stack = [
    {
      layer: layers,
      group: null,
    },
  ];

  while (stack.length > 0) {
    const { layer, group } = stack.pop();

    if (
      !(layer instanceof BaseLayer) ||
      (group !== null && !(group instanceof LayerGroup))
    )
      continue;

    const id = layer.get("id") || layer.id;

    if (id && id === targetId) {
      targetGroup = group;
      break;
    }

    if (layer instanceof LayerGroup) {
      stack.push(
        ...layer
          .getLayers()
          .getArray()
          .map(childLayer => ({
            layer: childLayer,
            group: layer,
          }))
      );
    }
  }
  return targetGroup;
}

// t- 添加图层
/**
 * @description 向地图中批量添加图层
 * @param {Map} map 地图对象
 * @param {Array} layers 图层数组
 */
export function addLayers(map, layers) {
  for (let i = 0; i < layers.length; i++) {
    const layer = layers[i];
    if (!layer || !(layer instanceof BaseLayer)) continue;
    map.addLayer(layer);
  }
}

// t- 移除图层

/**
 * @description 递归移除图层
 * @param {Map} map 地图对象
 * @param {BaseLayer} layer 图层对象
 */
export function removeLayerDeep(map, layer) {
  if (!(layer instanceof BaseLayer)) return;
  const group = getGroupById(map, layer.get("id") || layer.id);
  if (!group) return;
  group.getLayers().remove(layer);
}

/**
 * @description 向地图中批量移除图层
 * @param {Map} map 地图对象
 * @param {Array} layers 图层数组
 */
export function removeLayers(map, layers) {
  for (let i = 0; i < layers.length; i++) {
    const layer = layers[i];
    if (!layer || !(layer instanceof BaseLayer)) continue;
    removeLayerDeep(map, layer);
  }
}

/**
 * @description 根据图层id移除图层
 * @param {Map} map 地图对象
 * @param {String} id 图层id
 */
export function removeLayerById(map, id) {
  const layer = getLayerById(map, id);
  if (!layer) return;
  removeLayerDeep(map, layer);
}

/**
 * @description 根据条件移除图层
 * @param {Map} map 地图对象
 * @param {Function} condition 条件函数,接收图层对象、图层id和图层数组作为参数，返回布尔值
 * @param {BaseLayer} condition.layer 图层对象
 * @param {String} condition.id 图层id
 * @param {Array} condition.layers 图层数组
 */
export function removeLayerByCondition(map, condition) {
  removeLayers(map, getLayerByCondition(map, condition));
}
